﻿using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;

namespace PmSoft.Web.Abstractions.Authorization;

/// <summary>
/// 基于特性的授权处理器基类
/// </summary>
/// <typeparam name="TRequirement">授权要求类型，必须实现 IAuthorizationRequirement</typeparam>
/// <typeparam name="TAttribute">授权特性类型，必须是 Attribute 的子类</typeparam>
public abstract class AttributeAuthorizationHandler<TRequirement, TAttribute> : AuthorizationHandler<TRequirement>
	where TRequirement : IAuthorizationRequirement
	where TAttribute : Attribute
{
	/// <summary>
	/// 处理授权要求
	/// </summary>
	/// <param name="context">授权上下文</param>
	/// <param name="requirement">授权要求</param>
	/// <returns>Task</returns>
	protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, TRequirement requirement)
	{
		IEnumerable<TAttribute>? attributes = null;

		// 检查资源是否为 HttpContext
		if (context.Resource is HttpContext httpContext)
		{
			// 获取当前请求的 Endpoint
			var endpoint = httpContext.GetEndpoint();

			// 从 Endpoint 的元数据中提取所有 TAttribute 类型的特性
			attributes = endpoint?.Metadata.OfType<TAttribute>();
		}

		// 调用子类实现的 HandleRequirementAsync 方法，传递特性和上下文
		return HandleRequirementAsync(context, requirement, attributes ?? Enumerable.Empty<TAttribute>());
	}

	/// <summary>
	/// 子类必须实现的授权处理逻辑
	/// </summary>
	/// <param name="context">授权上下文</param>
	/// <param name="requirement">授权要求</param>
	/// <param name="attributes">与当前请求相关的授权特性集合</param>
	/// <returns>Task</returns>
	protected abstract Task HandleRequirementAsync(
		AuthorizationHandlerContext context,
		TRequirement requirement,
		IEnumerable<TAttribute> attributes);
}